/*
 * PROJECT:     ReactOS API tests
 * LICENSE:     MIT (https://spdx.org/licenses/MIT)
 * PURPOSE:     Tests for tan
 * COPYRIGHT:   Copyright 2021 Timo Kreuzer <timo.kreuzer@reactos.org>
 */

#if !defined(_CRTBLD) && !defined(_M_IX86)
#define _CRTBLD // we don't want inline tan!
#endif
#include "math_helpers.h"

#ifdef _MSC_VER
#pragma function(tan)
#endif

#if !defined(_M_IX86)
#define HAS_TANF
#elif (defined(TEST_UCRTBASE) || defined(TEST_STATIC_CRT))
#define HAS_LIBM_SSE2
#endif


// These are expected to match exactly
static TESTENTRY_DBL s_tan_exact_tests[] =
{
    { 0x0000000000000000 /*  0.000000 */, 0x0000000000000000 /*  0.000000 */ },
    { 0x8000000000000000 /* -0.000000 */, 0x8000000000000000 /* -0.000000 */ },
    { 0x7ff0000000000000 /*  1.#INF00 */, 0xfff8000000000000 /* -1.#IND00 */ },
    { 0x7ff0000000000001 /*  1.#SNAN0 */, 0x7ff8000000000001 /*  1.#QNAN0 */ },
    { 0x7ff7ffffffffffff /*  1.#SNAN0 */, 0x7fffffffffffffff /*  1.#QNAN0 */ },
    { 0x7ff8000000000000 /*  1.#QNAN0 */, 0x7ff8000000000000 /*  1.#QNAN0 */ },
    { 0x7ff8000000000001 /*  1.#QNAN0 */, 0x7ff8000000000001 /*  1.#QNAN0 */ },
    { 0x7fffffffffffffff /*  1.#QNAN0 */, 0x7fffffffffffffff /*  1.#QNAN0 */ },
    { 0xfff0000000000000 /* -1.#INF00 */, 0xfff8000000000000 /* -1.#IND00 */ },
    { 0xfff0000000000001 /* -1.#SNAN0 */, 0xfff8000000000001 /* -1.#QNAN0 */ },
    { 0xfff7ffffffffffff /* -1.#SNAN0 */, 0xffffffffffffffff /* -1.#QNAN0 */ },
    { 0xfff8000000000000 /* -1.#IND00 */, 0xfff8000000000000 /* -1.#IND00 */ },
    { 0xfff8000000000001 /* -1.#QNAN0 */, 0xfff8000000000001 /* -1.#QNAN0 */ },
    { 0xffffffffffffffff /* -1.#QNAN0 */, 0xffffffffffffffff /* -1.#QNAN0 */ },
};

void Test_tan_exact(void)
{
    for (int i = 0; i < _countof(s_tan_exact_tests); i++)
    {
        double x = u64_to_dbl(s_tan_exact_tests[i].x);
        double z = tan(x);
        ok_eq_dbl_exact("tan", s_tan_exact_tests[i].x, z, s_tan_exact_tests[i].result);
    }
}

// This table is autogenerated by `python gen_math_tests.py tan`
static TESTENTRY_DBL_APPROX s_tan_approx_tests[] =
{
//  {    x,                     {    y_rounded,               y_difference           } }
#if !(defined(_M_IX86) && defined(TEST_MSVCRT))
    {    -0x1.921fb54442d18p+0, {   -0x1.d02967c31cdb5p+53,     0x1.f3c72fe49aa2ap-3 }, 1 }, // tan(-1.5707963267948966) == -16331239353195369.756
#endif
    {    -0x1.85a6ec9bbc564p+0, {    -0x1.48292602db3dfp+4,   -0x1.59080789054e6p-52 }, 1 }, // tan(-1.5220783119405832) == -20.510046015889994508
    {    -0x1.792e23f335dafp+0, {    -0x1.4761710422f56p+3,    0x1.e3d55dad3df46p-52 }, 1 }, // tan(-1.4733602970862696) == -10.230644710616313666
    {    -0x1.6cb55b4aaf5fbp+0, {    -0x1.b2c590c42b471p+2,   -0x1.5d53989828de4p-52 }, 1 }, // tan(-1.4246422822319562) == -6.7933084407533085002
    {    -0x1.603c92a228e46p+0, {    -0x1.4440b5bd4111cp+2,   -0x1.abec5d54c2abap-52 }, 1 }, // tan(-1.3759242673776426) == -5.0664495800195052214
    {    -0x1.53c3c9f9a2692p+0, {    -0x1.0184ebdc8b27dp+2,   -0x1.211209852aafdp-52 }, 1 }, // tan(-1.3272062525233292) == -4.0237378743883003572
    {    -0x1.474b01511beddp+0, {    -0x1.a959c7c899705p+1,    0x1.e16a925ce3d25p-54 }, 1 }, // tan(-1.2784882376690156) == -3.3230523805131063697
    {    -0x1.3ad238a895729p+0, {    -0x1.68ac5e279dd0bp+1,   -0x1.d4cdade9a4c1ep-54 }, 1 }, // tan(-1.2297702228147023) == -2.8177602475585722303
    {    -0x1.2e5970000ef74p+0, {    -0x1.379ee31c647b3p+1,   -0x1.5e9c8a91c43d2p-54 }, 1 }, // tan(-1.1810522079603887) == -2.4345363510737683882
    {    -0x1.21e0a757887c0p+0, {    -0x1.10fa3b265671bp+1,   -0x1.d629f0bf05f70p-53 }, 1 }, // tan(-1.1323341931060753) == -2.1326364457317035047
    {    -0x1.1567deaf0200bp+0, {    -0x1.e33a2bc8b934bp+0,    0x1.d4ca996c14e19p-56 }, 1 }, // tan(-1.0836161782517617) == -1.8876063694999227506
    {    -0x1.08ef16067b857p+0, {    -0x1.af12917d3b0e2p+0,    0x1.f2079bbcce4a5p-56 }, 1 }, // tan(-1.0348981633974483) == -1.6838770800341582309
    {    -0x1.f8ec9abbea145p-1, {    -0x1.82d4f782a01c3p+0,    0x1.72f6a4728aa93p-54 }, 1 }, // tan(-0.9861801485431348) == -1.5110621160421124104
    {    -0x1.dffb096add1dcp-1, {    -0x1.5ca9a9f08c147p+0,    0x1.db383b0ec94fbp-54 }, 1 }, // tan(-0.9374621336888214) == -1.3619638645432857817
    {    -0x1.c7097819d0273p-1, {    -0x1.3b3f45fb0d102p+0,   -0x1.b6d38abd7652cp-58 }, 1 }, // tan(-0.8887441188345079) == -1.2314342248837992837
    {    -0x1.ae17e6c8c330ap-1, {    -0x1.1d9debf5bcdadp+0,    0x1.4c70a3c0c8823p-54 }, 1 }, // tan(-0.8400261039801944) == -1.115690944189604722
    {    -0x1.95265577b63a1p-1, {    -0x1.030b3d77c014ep+0,    0x1.3667d9fcd7a86p-54 }, 1 }, // tan(-0.7913080891258809) == -1.011890260444562472
    {    -0x1.7c34c426a9438p-1, {    -0x1.d5f079b0e6c4cp-1,    0x1.5688a6674ac98p-56 }, 1 }, // tan(-0.7425900742715674) == -0.91785030636254692302
    {    -0x1.634332d59c4cfp-1, {    -0x1.a9ea6c741d9ebp-1,    0x1.f3c3e52eca656p-55 }, 1 }, // tan(-0.6938720594172539) == -0.83186663548877720764
    {    -0x1.4a51a1848f566p-1, {    -0x1.8152f115f047fp-1,   -0x1.9227d5686fc02p-56 }, 1 }, // tan(-0.6451540445629405) == -0.75258592026524686562
    {    -0x1.31601033825fdp-1, {    -0x1.5b9b116956dd4p-1,   -0x1.021da723d81edp-56 }, 1 }, // tan(-0.596436029708627) == -0.67891745005493443777
    {    -0x1.186e7ee275694p-1, {    -0x1.384df6b48888ep-1,   -0x1.c79d9269e0dfdp-56 }, 1 }, // tan(-0.5477180148543135) == -0.60996981576706035516
    {    -0x1.fef9db22d0e56p-2, {    -0x1.170adce3a684cp-1,    0x1.155476f2da1afp-56 }, 1 }, // tan(-0.499) == -0.54500475195823970427
    {    -0x1.0000000000000p-1, {    -0x1.17b4f5bf3474ap-1,   -0x1.0c5e59201e209p-55 }, 1 }, // tan(-0.5) == -0.54630248984379051326
    {    -0x1.e8ba2e8ba2e8cp-2, {    -0x1.08c7caac28aa4p-1,    0x1.28cd16180fba1p-55 }, 1 }, // tan(-0.4772727272727273) == -0.51714928962276870529
    {    -0x1.d1745d1745d18p-2, {    -0x1.f466d6406bb86p-2,    0x1.9028ce89507bdp-56 }, 1 }, // tan(-0.4545454545454546) == -0.48867354171937225134
    {    -0x1.ba2e8ba2e8ba4p-2, {    -0x1.d7e21b76dc1a9p-2,   -0x1.819c73e1623a4p-63 }, 1 }, // tan(-0.4318181818181819) == -0.46082346833193327268
    {    -0x1.a2e8ba2e8ba30p-2, {    -0x1.bbf4be4924d13p-2,    0x1.210bfe1eac791p-57 }, 1 }, // tan(-0.40909090909090917) == -0.43355080911096981804
    {    -0x1.8ba2e8ba2e8bcp-2, {    -0x1.a092eb7d16791p-2,   -0x1.17dd013191ce5p-57 }, 1 }, // tan(-0.38636363636363646) == -0.40681045485472917193
    {    -0x1.745d1745d1748p-2, {    -0x1.85b18d5ff2a82p-2,    0x1.c73ccb0f5765fp-56 }, 1 }, // tan(-0.36363636363636376) == -0.38056012056464547407
    {    -0x1.5d1745d1745d4p-2, {    -0x1.6b46381f7ab06p-2,    0x1.ef981da78f64dp-56 }, 1 }, // tan(-0.34090909090909105) == -0.35476005260595430779
    {    -0x1.45d1745d17460p-2, {    -0x1.5147181f7a3e1p-2,   -0x1.f38537f209091p-57 }, 1 }, // tan(-0.31818181818181834) == -0.32937276546596024018
    {    -0x1.2e8ba2e8ba2ecp-2, {    -0x1.37aae2091da45p-2,   -0x1.28d36d7bc8acfp-60 }, 1 }, // tan(-0.29545454545454564) == -0.3043628042281947842
    {    -0x1.1745d1745d178p-2, {    -0x1.1e68c45a69fa8p-2,   -0x1.3400e52091ac5p-56 }, 1 }, // tan(-0.27272727272727293) == -0.27969652940600521767
    {    -0x1.0000000000004p-2, {    -0x1.05785a43c4c5ap-2,   -0x1.47e7420a285bep-57 }, 1 }, // tan(-0.2500000000000002) == -0.25534192122103650303
    {    -0x1.d1745d1745d20p-3, {    -0x1.d9a33f4fbd685p-3,    0x1.154219988e9c3p-57 }, 1 }, // tan(-0.22727272727272751) == -0.23126840078446177865
    {    -0x1.a2e8ba2e8ba38p-3, {    -0x1.a8d9cc2f752f2p-3,    0x1.0dc2a8dcacd37p-57 }, 1 }, // tan(-0.2045454545454548) == -0.20744666595296439683
    {    -0x1.745d1745d1750p-3, {    -0x1.788595522f833p-3,    0x1.48cb47f93cc67p-57 }, 1 }, // tan(-0.1818181818181821) == -0.18384853989658863302
    {    -0x1.45d1745d17468p-3, {    -0x1.48985912bccaap-3,   -0x1.9ba520513e51cp-57 }, 1 }, // tan(-0.1590909090909094) == -0.16044683063919269467
    {    -0x1.1745d1745d180p-3, {    -0x1.19044864d16f4p-3,   -0x1.c642f9fbf57f4p-57 }, 1 }, // tan(-0.1363636363636367) == -0.13721520002052724051
    {    -0x1.d1745d1745d30p-4, {    -0x1.d377eca4ea002p-4,   -0x1.1caa3d80e4684p-61 }, 1 }, // tan(-0.11363636363636398) == -0.11412804068697826647
    {    -0x1.745d1745d1760p-4, {    -0x1.756490c3f31dbp-4,    0x1.b6724a0e4e6bfp-59 }, 1 }, // tan(-0.09090909090909127) == -0.091160359849886612809
    {    -0x1.1745d1745d190p-4, {    -0x1.17b4cf79cc8d0p-4,   -0x1.3bc015ade5d5cp-59 }, 1 }, // tan(-0.06818181818181857) == -0.068287668659454017125
    {    -0x1.745d1745d1780p-5, {    -0x1.749ecbcd3dedbp-5,   -0x1.14076fc22d284p-59 }, 1 }, // tan(-0.04545454545454586) == -0.045485876131292813301
    {    -0x1.745d1745d17c0p-6, {    -0x1.746d81cc44785p-6,    0x1.e86df438a8135p-60 }, 1 }, // tan(-0.02272727272727315) == -0.022731186633854887507
    {   -0x1.0000000000000p-51, {   -0x1.0000000000000p-51,  -0x1.5555555555555p-155 }, 1 }, // tan(-4.440892098500626e-16) == -4.4408920985006261617e-16
    {   -0x1.0000000000000p-52, {   -0x1.0000000000000p-52,  -0x1.5555555555555p-158 }, 1 }, // tan(-2.220446049250313e-16) == -2.2204460492503130808e-16
    {   -0x1.5555555555556p-53, {   -0x1.5555555555556p-53,  -0x1.948b0fcd6e9e3p-160 }, 1 }, // tan(-1.4802973661668756e-16) == -1.4802973661668755516e-16
    {   -0x1.5555555555556p-54, {   -0x1.5555555555556p-54,  -0x1.948b0fcd6e9e3p-163 }, 1 }, // tan(-7.401486830834378e-17) == -7.4014868308343777579e-17
    {                 0x0.0p+0, {                 0x0.0p+0,                 0x0.0p+0 }, 1 }, // tan(0.0) == 0.0
    {    0x1.5555555555554p-54, {    0x1.5555555555554p-54,   0x1.948b0fcd6e9dcp-163 }, 1 }, // tan(7.401486830834375e-17) == 7.4014868308343752927e-17
    {    0x1.5555555555554p-53, {    0x1.5555555555554p-53,   0x1.948b0fcd6e9dcp-160 }, 1 }, // tan(1.480297366166875e-16) == 1.4802973661668750585e-16
    {    0x1.0000000000000p-52, {    0x1.0000000000000p-52,   0x1.5555555555555p-158 }, 1 }, // tan(2.220446049250313e-16) == 2.2204460492503130808e-16
    {    0x1.0000000000000p-51, {    0x1.0000000000000p-51,   0x1.5555555555555p-155 }, 1 }, // tan(4.440892098500626e-16) == 4.4408920985006261617e-16
    {     0x1.745d1745d17c0p-6, {     0x1.746d81cc44785p-6,   -0x1.e86df438a8135p-60 }, 1 }, // tan(0.02272727272727315) == 0.022731186633854887507
    {     0x1.745d1745d1780p-5, {     0x1.749ecbcd3dedbp-5,    0x1.14076fc22d284p-59 }, 1 }, // tan(0.04545454545454586) == 0.045485876131292813301
    {     0x1.1745d1745d190p-4, {     0x1.17b4cf79cc8d0p-4,    0x1.3bc015ade5d5cp-59 }, 1 }, // tan(0.06818181818181857) == 0.068287668659454017125
    {     0x1.745d1745d1760p-4, {     0x1.756490c3f31dbp-4,   -0x1.b6724a0e4e6bfp-59 }, 1 }, // tan(0.09090909090909127) == 0.091160359849886612809
    {     0x1.d1745d1745d30p-4, {     0x1.d377eca4ea002p-4,    0x1.1caa3d80e4684p-61 }, 1 }, // tan(0.11363636363636398) == 0.11412804068697826647
    {     0x1.1745d1745d180p-3, {     0x1.19044864d16f4p-3,    0x1.c642f9fbf57f4p-57 }, 1 }, // tan(0.1363636363636367) == 0.13721520002052724051
    {     0x1.45d1745d17468p-3, {     0x1.48985912bccaap-3,    0x1.9ba520513e51cp-57 }, 1 }, // tan(0.1590909090909094) == 0.16044683063919269467
    {     0x1.745d1745d1750p-3, {     0x1.788595522f833p-3,   -0x1.48cb47f93cc67p-57 }, 1 }, // tan(0.1818181818181821) == 0.18384853989658863302
    {     0x1.a2e8ba2e8ba38p-3, {     0x1.a8d9cc2f752f2p-3,   -0x1.0dc2a8dcacd37p-57 }, 1 }, // tan(0.2045454545454548) == 0.20744666595296439683
    {     0x1.d1745d1745d20p-3, {     0x1.d9a33f4fbd685p-3,   -0x1.154219988e9c3p-57 }, 1 }, // tan(0.22727272727272751) == 0.23126840078446177865
    {     0x1.0000000000004p-2, {     0x1.05785a43c4c5ap-2,    0x1.47e7420a285bep-57 }, 1 }, // tan(0.2500000000000002) == 0.25534192122103650303
    {     0x1.1745d1745d178p-2, {     0x1.1e68c45a69fa8p-2,    0x1.3400e52091ac5p-56 }, 1 }, // tan(0.27272727272727293) == 0.27969652940600521767
    {     0x1.2e8ba2e8ba2ecp-2, {     0x1.37aae2091da45p-2,    0x1.28d36d7bc8acfp-60 }, 1 }, // tan(0.29545454545454564) == 0.3043628042281947842
    {     0x1.45d1745d17460p-2, {     0x1.5147181f7a3e1p-2,    0x1.f38537f209091p-57 }, 1 }, // tan(0.31818181818181834) == 0.32937276546596024018
    {     0x1.5d1745d1745d4p-2, {     0x1.6b46381f7ab06p-2,   -0x1.ef981da78f64dp-56 }, 1 }, // tan(0.34090909090909105) == 0.35476005260595430779
    {     0x1.745d1745d1748p-2, {     0x1.85b18d5ff2a82p-2,   -0x1.c73ccb0f5765fp-56 }, 1 }, // tan(0.36363636363636376) == 0.38056012056464547407
    {     0x1.8ba2e8ba2e8bcp-2, {     0x1.a092eb7d16791p-2,    0x1.17dd013191ce5p-57 }, 1 }, // tan(0.38636363636363646) == 0.40681045485472917193
    {     0x1.a2e8ba2e8ba30p-2, {     0x1.bbf4be4924d13p-2,   -0x1.210bfe1eac791p-57 }, 1 }, // tan(0.40909090909090917) == 0.43355080911096981804
    {     0x1.ba2e8ba2e8ba4p-2, {     0x1.d7e21b76dc1a9p-2,    0x1.819c73e1623a4p-63 }, 1 }, // tan(0.4318181818181819) == 0.46082346833193327268
    {     0x1.d1745d1745d18p-2, {     0x1.f466d6406bb86p-2,   -0x1.9028ce89507bdp-56 }, 1 }, // tan(0.4545454545454546) == 0.48867354171937225134
    {     0x1.e8ba2e8ba2e8cp-2, {     0x1.08c7caac28aa4p-1,   -0x1.28cd16180fba1p-55 }, 1 }, // tan(0.4772727272727273) == 0.51714928962276870529
    {     0x1.0000000000000p-1, {     0x1.17b4f5bf3474ap-1,    0x1.0c5e59201e209p-55 }, 1 }, // tan(0.5) == 0.54630248984379051326
    {     0x1.0083126e978d5p-1, {     0x1.185f3e353789ap-1,   -0x1.1164e2f8dc326p-55 }, 1 }, // tan(0.501) == 0.5476016464197243897
    {     0x1.1968b9587f770p-1, {     0x1.39a5b1895ef0fp-1,    0x1.69076f1898249p-55 }, 1 }, // tan(0.5496271057634043) == 0.61259226610079224346
    {     0x1.324e60426760cp-1, {     0x1.5cf7a819e93efp-1,    0x1.c1f568456e356p-56 }, 1 }, // tan(0.5982542115268088) == 0.68157697025583088509
    {     0x1.4b34072c4f4a7p-1, {     0x1.82b607606becfp-1,   -0x1.3d8f67e5f35dfp-56 }, 1 }, // tan(0.6468813172902131) == 0.75529501964589394413
    {     0x1.6419ae1637343p-1, {     0x1.ab55d25bca8e2p-1,    0x1.4bc370a5ac8f2p-57 }, 1 }, // tan(0.6955084230536176) == 0.83463914270876339085
    {     0x1.7cff55001f1dep-1, {     0x1.d76639191a092p-1,    0x1.e083312b5f5f2p-55 }, 1 }, // tan(0.7441355288170219) == 0.92070177489678633678
    {     0x1.95e4fbea0707ap-1, {     0x1.03cc7485ba1c0p+0,   -0x1.ffd40f6f90912p-54 }, 1 }, // tan(0.7927626345804264) == 1.0148384882432849308
    {     0x1.aecaa2d3eef15p-1, {     0x1.1e66d60e326d4p+0,   -0x1.61a7ab456a939p-54 }, 1 }, // tan(0.8413897403438307) == 1.1187566551838487371
    {     0x1.c7b049bdd6db0p-1, {     0x1.3c117f3d5196bp+0,   -0x1.eaea7607b3a57p-54 }, 1 }, // tan(0.8900168461072351) == 1.2346419834808225514
    {     0x1.e095f0a7bec4cp-1, {     0x1.5d8723ffe6398p+0,    0x1.b3677f868b65fp-55 }, 1 }, // tan(0.9386439518706395) == 1.3653433322672068801
    {     0x1.f97b9791a6ae7p-1, {     0x1.83c0173e2d001p+0,   -0x1.54207765ad0b9p-55 }, 1 }, // tan(0.9872710576340439) == 1.5146498228832571873
    {     0x1.09309f3dc74c1p+0, {     0x1.b00e5a163e86fp+0,    0x1.36a110d4cecd5p-54 }, 1 }, // tan(1.0358981633974482) == 1.6877189926440470787
    {     0x1.15a372b2bb40fp+0, {     0x1.e44a7f426cc8ap+0,    0x1.3733708d99df4p-55 }, 1 }, // tan(1.0845252691608527) == 1.8917617356462721805
    {     0x1.22164627af35dp+0, {     0x1.118f3cd8a0a0ap+1,   -0x1.4d890bd026cb3p-53 }, 1 }, // tan(1.1331523749242571) == 2.1371837671042655745
    {     0x1.2e89199ca32abp+0, {     0x1.384442285e0a4p+1,    0x1.e023f3b8735f6p-55 }, 1 }, // tan(1.1817794806876616) == 2.4395830819231197305
    {     0x1.3afbed11971f8p+0, {     0x1.69671e3a41aecp+1,    0x1.521a4291c1306p-54 }, 1 }, // tan(1.2304065864510658) == 2.8234594139533922453
    {     0x1.476ec0868b146p+0, {     0x1.aa316a5fb43c9p+1,   -0x1.52dbeccfa5e16p-55 }, 1 }, // tan(1.2790336922144703) == 3.3296330420784880554
    {     0x1.53e193fb7f094p+0, {     0x1.02052d9240193p+2,    0x1.f3c7273c87f91p-53 }, 1 }, // tan(1.3276607979778747) == 4.0315660408235942605
    {     0x1.6054677072fe1p+0, {     0x1.44dfe447af0fdp+2,    0x1.9921e6edfc0f1p-53 }, 1 }, // tan(1.376287903741279) == 5.0761652660405591318
    {     0x1.6cc73ae566f2fp+0, {     0x1.b398a2b7194e6p+2,   -0x1.41da4eda108d7p-56 }, 1 }, // tan(1.4249150095046834) == 6.8061911380839088362
    {     0x1.793a0e5a5ae7dp+0, {     0x1.47ff1e9ecf9bap+3,    0x1.858f5bd530970p-51 }, 1 }, // tan(1.4735421152680879) == 10.249892530610726703
    {     0x1.85ace1cf4edcbp+0, {     0x1.48c674106788dp+4,   -0x1.7df7c58540c45p-50 }, 1 }, // tan(1.5221692210314923) == 20.548450531081970734
#if !(defined(_M_IX86) && defined(TEST_MSVCRT))
    {     0x1.921fb54442d18p+0, {    0x1.d02967c31cdb5p+53,    -0x1.f3c72fe49aa2ap-3 }, 1 }, // tan(1.5707963267948966) == 16331239353195369.756
#endif
    {     0x1.07eb3e0e397c5p+5, {    -0x1.3e4f101260dc1p+8,   -0x1.2b5a2b39a6a8bp-46 }, 1 }, // tan(32.989864455346414) == -318.30883898606051004
    {     0x1.0e30855693b63p+5, {    -0x1.fe64dee19cc97p-1,    0x1.77d5738519368p-55 }, 1 }, // tan(33.77369182241707) == -0.99686333183344085029
#if !(defined(_M_IX86) && defined(TEST_MSVCRT))
    {     0x1.1475cc9eedf01p+5, {    0x1.3ddc5bce200bbp-49,   0x1.15860679cd558p-103 }, 1 }, // tan(34.55751918948773) == 2.2056021997384124344e-15
#endif
    {     0x1.1abb13e74829ep+5, {     0x1.fe64dee19cc66p-1,    0x1.002beedbbd0f9p-55 }, 1 }, // tan(35.34134655655838) == 0.99686333183343547872
    {     0x1.21005b2fa263cp+5, {     0x1.3e4f10125faffp+8,   -0x1.2349bf9baab7cp-48 }, 1 }, // tan(36.125173923629035) == 318.30883898578752729
};

void Test_tan_approx(void)
{
    for (int i = 0; i < _countof(s_tan_approx_tests); i++)
    {
        double x = s_tan_approx_tests[i].x;
        double expected = s_tan_approx_tests[i].expected.rounded;
        double z = tan(x);
        int64_t error = abs(ulp_error_precise(&s_tan_approx_tests[i].expected, z));
        ok(error <= s_tan_approx_tests[i].max_error,
            "tan(%.17e) = %.17e, expected %.17e, error %I64d ULPs, max %u ULPs\n",
            x, z, expected, error, s_tan_approx_tests[i].max_error);
    }
}

#ifdef HAS_TANF

// These are expected to match exactly
static TESTENTRY_DBL s_tanf_exact_tests[] =
{
    { 0x00000000 /*  0.000000 */, 0x00000000 /*  0.000000 */ },
    { 0x80000000 /* -0.000000 */, 0x00000000 /*  0.000000 */ },
    { 0x7f800000 /*  1.#INF00 */, 0x00000000 /*  0.000000 */ },
    { 0x7f800001 /*  1.#SNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0x7fBFffff /*  1.#SNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0x7fC00000 /*  1.#QNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0x7fC80001 /*  1.#QNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0x7fFfffff /*  1.#QNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0xff800000 /* -1.#INF00 */, 0x00000000 /*  0.000000 */ },
    { 0xff800001 /* -1.#SNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0xffBfffff /* -1.#SNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0xffC00000 /* -1.#IND00 */, 0x00000000 /*  0.000000 */ },
    { 0xfff80001 /* -1.#QNAN0 */, 0x00000000 /*  0.000000 */ },
    { 0xffffffff /* -1.#QNAN0 */, 0x00000000 /*  0.000000 */ },
};

void Test_tanf_exact(void)
{
    for (int i = 0; i < _countof(s_tanf_exact_tests); i++)
    {
        float x = u64_to_dbl(s_tanf_exact_tests[i].x);
        float z = tanf(x);
        ok_eq_flt_exact("tanf", s_tanf_exact_tests[i].x, z, s_tanf_exact_tests[i].result);
    }
}

#endif // HAS_TANF

#if defined(HAS_TANF) || defined(HAS_LIBM_SSE2)

static TESTENTRY_DBL_APPROX s_tanf_approx_tests[] =
{
//  {    x,                     {    y_rounded,               y_difference           } }
    {    -0x1.921fb60000000p+0, {    0x1.5d14946dc9897p+24,    0x1.759086954a140p-30 }, 1 }, // tanf(-1.5707963705062866) == 22877332.428856459874
    {    -0x1.85a6ec0000000p+0, {    -0x1.482915fa9ee30p+4,   -0x1.bbeceea93d6b7p-50 }, 1 }, // tanf(-1.522078275680542) == -20.510030726420326749
    {    -0x1.792e240000000p+0, {    -0x1.476171ad10b84p+3,   -0x1.5815b396155f9p-51 }, 1 }, // tanf(-1.473360300064087) == -10.230645025270640389
    {    -0x1.6cb55c0000000p+0, {    -0x1.b2c5991d60457p+2,    0x1.b292872ff2d76p-53 }, 1 }, // tanf(-1.4246423244476318) == -6.7933104311824397462
    {    -0x1.603c920000000p+0, {    -0x1.4440b18419367p+2,   -0x1.750eac0a12690p-55 }, 1 }, // tanf(-1.3759242296218872) == -5.0664485731148039398
    {    -0x1.53c3ca0000000p+0, {    -0x1.0184ebf7e6818p+2,   -0x1.1aebbc20cd7b5p-52 }, 1 }, // tanf(-1.3272062540054321) == -4.0237378998663404739
    {    -0x1.474b020000000p+0, {    -0x1.a959cbe5ad45ep+1,   -0x1.1f19c933c0298p-53 }, 1 }, // tanf(-1.278488278388977) == -3.3230528708905203851
    {    -0x1.3ad2380000000p+0, {    -0x1.68ac5b3610f2ep+1,    0x1.ce3a53388d573p-53 }, 1 }, // tanf(-1.2297701835632324) == -2.8177598966593879964
    {    -0x1.2e59700000000p+0, {    -0x1.379ee31c30a5cp+1,    0x1.7fd7a0966bccep-53 }, 1 }, // tanf(-1.1810522079467773) == -2.4345363509794831215
    {    -0x1.21e0a80000000p+0, {    -0x1.10fa3cf9ad29bp+1,   -0x1.18a3dc72f2dc1p-54 }, 1 }, // tanf(-1.1323342323303223) == -2.1326366633532650217
    {    -0x1.1567de0000000p+0, {    -0x1.e33a28aa2717fp+0,    0x1.68562cb63425ep-54 }, 1 }, // tanf(-1.0836161375045776) == -1.8876061835681806951
    {    -0x1.08ef160000000p+0, {    -0x1.af1291645e0ecp+0,   -0x1.82c32a8763e67p-55 }, 1 }, // tanf(-1.0348981618881226) == -1.6838770742452267435
    {    -0x1.f8ec9a0000000p-1, {    -0x1.82d4f64e228edp+0,    0x1.96d28d6d91903p-54 }, 1 }, // tanf(-0.9861801266670227) == -1.5110620442160850547
    {    -0x1.dffb0a0000000p-1, {    -0x1.5ca9aac56f660p+0,   -0x1.cf1198d68e402p-54 }, 1 }, // tanf(-0.9374621510505676) == -1.3619639141101275053
    {    -0x1.c709780000000p-1, {    -0x1.3b3f45da9295cp+0,    0x1.63bd7d7c7576bp-54 }, 1 }, // tanf(-0.8887441158294678) == -1.2314342173218254867
    {    -0x1.ae17e60000000p-1, {    -0x1.1d9deb1467c2fp+0,    0x1.d93dccaaa6e15p-55 }, 1 }, // tanf(-0.8400260806083679) == -1.11569089172531805
    {    -0x1.9526560000000p-1, {    -0x1.030b3e01ab2b9p+0,    0x1.f0be43b2a457bp-54 }, 1 }, // tanf(-0.7913081049919128) == -1.0118902925561724693
    {    -0x1.7c34c40000000p-1, {    -0x1.d5f07969ab903p-1,    0x1.d7d4d48e87fc3p-57 }, 1 }, // tanf(-0.742590069770813) == -0.91785029807013561563
    {    -0x1.6343320000000p-1, {    -0x1.a9ea6b0aafabap-1,    0x1.85b16fcacb454p-56 }, 1 }, // tanf(-0.6938720345497131) == -0.83186659341284683419
    {    -0x1.4a51a20000000p-1, {    -0x1.8152f1d74b1a8p-1,    0x1.dd7a25caf317ap-55 }, 1 }, // tanf(-0.6451540589332581) == -0.75258594277470520037
    {    -0x1.3160100000000p-1, {    -0x1.5b9b111e16825p-1,   -0x1.cd18dbc056bb1p-57 }, 1 }, // tanf(-0.5964360237121582) == -0.67891744129451993135
    {    -0x1.186e7e0000000p-1, {    -0x1.384df57dd15a7p-1,   -0x1.f2f27bdb30755p-55 }, 1 }, // tanf(-0.5477179884910583) == -0.60996977959500936342
    {    -0x1.fef9dc0000000p-2, {    -0x1.170add731774cp-1,   -0x1.b4799c456e9b6p-55 }, 1 }, // tanf(-0.49900001287460327) == -0.54500476865698881682
    {    -0x1.0000000000000p-1, {    -0x1.17b4f5bf3474ap-1,   -0x1.0c5e59201e209p-55 }, 1 }, // tanf(-0.5) == -0.54630248984379051326
    {    -0x1.e8ba2e0000000p-2, {    -0x1.08c7ca53ab12cp-1,    0x1.f57d7c1223293p-58 }, 1 }, // tanf(-0.47727271914482117) == -0.51714927932110787298
    {    -0x1.d1745e0000000p-2, {    -0x1.f466d760b947fp-2,   -0x1.21b5240e6aa7ap-56 }, 1 }, // tanf(-0.4545454680919647) == -0.48867355850081391394
    {    -0x1.ba2e8c0000000p-2, {    -0x1.d7e21be7b824ep-2,   -0x1.280c597324109p-58 }, 1 }, // tanf(-0.4318181872367859) == -0.46082347490122266677
    {    -0x1.a2e8ba0000000p-2, {    -0x1.bbf4be11d9713p-2,   -0x1.1fd834abca2e6p-56 }, 1 }, // tanf(-0.40909090638160706) == -0.43355080589241020045
    {    -0x1.8ba2e80000000p-2, {    -0x1.a092eaa41806cp-2,    0x1.7c80008b49c5bp-58 }, 1 }, // tanf(-0.3863636255264282) == -0.40681044222401995842
    {    -0x1.745d180000000p-2, {    -0x1.85b18e3517fa5p-2,    0x1.4fde597478211p-58 }, 1 }, // tanf(-0.3636363744735718) == -0.38056013297136309192
    {    -0x1.5d17460000000p-2, {    -0x1.6b463853e1f6ap-2,    0x1.3ea3b0f12ae57p-56 }, 1 }, // tanf(-0.34090909361839294) == -0.35476005565623456799
    {    -0x1.45d1740000000p-2, {    -0x1.514717b849998p-2,    0x1.fd76e2939aa2bp-59 }, 1 }, // tanf(-0.3181818127632141) == -0.32937275945951105182
    {    -0x1.2e8ba20000000p-2, {    -0x1.37aae10ad4551p-2,   -0x1.f30aa8f232fc7p-60 }, 1 }, // tanf(-0.2954545319080353) == -0.30436278942678024642
    {    -0x1.1745d20000000p-2, {    -0x1.1e68c4f0f95f7p-2,   -0x1.1395a0da02fbap-58 }, 1 }, // tanf(-0.27272728085517883) == -0.27969653816975842782
    {    -0x1.0000000000000p-2, {    -0x1.05785a43c4c56p-2,    0x1.9c6bfe7769a3dp-58 }, 1 }, // tanf(-0.25) == -0.2553419212210362665
    {    -0x1.d1745e0000000p-3, {    -0x1.d9a34044ea216p-3,   -0x1.fbfe898f560d7p-57 }, 1 }, // tanf(-0.22727273404598236) == -0.23126840791998466696
    {    -0x1.a2e8ba0000000p-3, {    -0x1.a8d9cbfee8c43p-3,    0x1.858552a968917p-59 }, 1 }, // tanf(-0.20454545319080353) == -0.20744666454001689251
    {    -0x1.745d180000000p-3, {    -0x1.78859612a9102p-3,    0x1.0b201e0d80102p-58 }, 1 }, // tanf(-0.1818181872367859) == -0.18384854549834278219
    {    -0x1.45d1740000000p-3, {    -0x1.489858b34005fp-3,   -0x1.6ada9662e24cfp-57 }, 1 }, // tanf(-0.15909090638160706) == -0.16044682786014428528
    {    -0x1.1745d20000000p-3, {    -0x1.190448f315625p-3,   -0x1.0c5ee14b4d884p-57 }, 1 }, // tanf(-0.13636364042758942) == -0.13721520416099611989
    {    -0x1.d1745e0000000p-4, {    -0x1.d377ed90ac31dp-4,    0x1.8d56873a5ced9p-59 }, 1 }, // tanf(-0.11363636702299118) == -0.11412804411771699806
    {    -0x1.745d180000000p-4, {    -0x1.7564917fadbdap-4,   -0x1.1122d5adaf096p-59 }, 1 }, // tanf(-0.09090909361839294) == -0.091160362581703154502
    {    -0x1.1745d20000000p-4, {    -0x1.17b4d00616260p-4,    0x1.d3629eb18cc93p-58 }, 1 }, // tanf(-0.06818182021379471) == -0.068287670700905683024
    {    -0x1.745d180000000p-5, {    -0x1.749ecc87cf126p-5,   -0x1.dcf4ecf92b84dp-59 }, 1 }, // tanf(-0.04545454680919647) == -0.045485877488746151899
    {    -0x1.745d180000000p-6, {    -0x1.746d82868b9cfp-6,    0x1.2e64b511833eap-63 }, 1 }, // tanf(-0.022727273404598236) == -0.022731187311529950934
    {   -0x1.0000000000000p-51, {   -0x1.0000000000000p-51,  -0x1.5555555555555p-155 }, 1 }, // tanf(-4.440892098500626e-16) == -4.4408920985006261617e-16
    {   -0x1.0000000000000p-52, {   -0x1.0000000000000p-52,  -0x1.5555555555555p-158 }, 1 }, // tanf(-2.220446049250313e-16) == -2.2204460492503130808e-16
    {   -0x1.5555560000000p-53, {   -0x1.5555560000000p-53,  -0x1.948b122c3f36fp-160 }, 1 }, // tanf(-1.4802974102831747e-16) == -1.4802974102831747234e-16
    {   -0x1.5555560000000p-54, {   -0x1.5555560000000p-54,  -0x1.948b122c3f36fp-163 }, 1 }, // tanf(-7.401487051415874e-17) == -7.401487051415873617e-17
    {                 0x0.0p+0, {                 0x0.0p+0,                 0x0.0p+0 }, 1 }, // tanf(0.0) == 0.0
    {    0x1.5555560000000p-54, {    0x1.5555560000000p-54,   0x1.948b122c3f36fp-163 }, 1 }, // tanf(7.401487051415874e-17) == 7.401487051415873617e-17
    {    0x1.5555560000000p-53, {    0x1.5555560000000p-53,   0x1.948b122c3f36fp-160 }, 1 }, // tanf(1.4802974102831747e-16) == 1.4802974102831747234e-16
    {    0x1.0000000000000p-52, {    0x1.0000000000000p-52,   0x1.5555555555555p-158 }, 1 }, // tanf(2.220446049250313e-16) == 2.2204460492503130808e-16
    {    0x1.0000000000000p-51, {    0x1.0000000000000p-51,   0x1.5555555555555p-155 }, 1 }, // tanf(4.440892098500626e-16) == 4.4408920985006261617e-16
    {     0x1.745d180000000p-6, {     0x1.746d82868b9cfp-6,   -0x1.2e64b511833eap-63 }, 1 }, // tanf(0.022727273404598236) == 0.022731187311529950934
    {     0x1.745d180000000p-5, {     0x1.749ecc87cf126p-5,    0x1.dcf4ecf92b84dp-59 }, 1 }, // tanf(0.04545454680919647) == 0.045485877488746151899
    {     0x1.1745d20000000p-4, {     0x1.17b4d00616260p-4,   -0x1.d3629eb18cc93p-58 }, 1 }, // tanf(0.06818182021379471) == 0.068287670700905683024
    {     0x1.745d180000000p-4, {     0x1.7564917fadbdap-4,    0x1.1122d5adaf096p-59 }, 1 }, // tanf(0.09090909361839294) == 0.091160362581703154502
    {     0x1.d1745e0000000p-4, {     0x1.d377ed90ac31dp-4,   -0x1.8d56873a5ced9p-59 }, 1 }, // tanf(0.11363636702299118) == 0.11412804411771699806
    {     0x1.1745d20000000p-3, {     0x1.190448f315625p-3,    0x1.0c5ee14b4d884p-57 }, 1 }, // tanf(0.13636364042758942) == 0.13721520416099611989
    {     0x1.45d1740000000p-3, {     0x1.489858b34005fp-3,    0x1.6ada9662e24cfp-57 }, 1 }, // tanf(0.15909090638160706) == 0.16044682786014428528
    {     0x1.745d180000000p-3, {     0x1.78859612a9102p-3,   -0x1.0b201e0d80102p-58 }, 1 }, // tanf(0.1818181872367859) == 0.18384854549834278219
    {     0x1.a2e8ba0000000p-3, {     0x1.a8d9cbfee8c43p-3,   -0x1.858552a968917p-59 }, 1 }, // tanf(0.20454545319080353) == 0.20744666454001689251
    {     0x1.d1745e0000000p-3, {     0x1.d9a34044ea216p-3,    0x1.fbfe898f560d7p-57 }, 1 }, // tanf(0.22727273404598236) == 0.23126840791998466696
    {     0x1.0000000000000p-2, {     0x1.05785a43c4c56p-2,   -0x1.9c6bfe7769a3dp-58 }, 1 }, // tanf(0.25) == 0.2553419212210362665
    {     0x1.1745d20000000p-2, {     0x1.1e68c4f0f95f7p-2,    0x1.1395a0da02fbap-58 }, 1 }, // tanf(0.27272728085517883) == 0.27969653816975842782
    {     0x1.2e8ba20000000p-2, {     0x1.37aae10ad4551p-2,    0x1.f30aa8f232fc7p-60 }, 1 }, // tanf(0.2954545319080353) == 0.30436278942678024642
    {     0x1.45d1740000000p-2, {     0x1.514717b849998p-2,   -0x1.fd76e2939aa2bp-59 }, 1 }, // tanf(0.3181818127632141) == 0.32937275945951105182
    {     0x1.5d17460000000p-2, {     0x1.6b463853e1f6ap-2,   -0x1.3ea3b0f12ae57p-56 }, 1 }, // tanf(0.34090909361839294) == 0.35476005565623456799
    {     0x1.745d180000000p-2, {     0x1.85b18e3517fa5p-2,   -0x1.4fde597478211p-58 }, 1 }, // tanf(0.3636363744735718) == 0.38056013297136309192
    {     0x1.8ba2e80000000p-2, {     0x1.a092eaa41806cp-2,   -0x1.7c80008b49c5bp-58 }, 1 }, // tanf(0.3863636255264282) == 0.40681044222401995842
    {     0x1.a2e8ba0000000p-2, {     0x1.bbf4be11d9713p-2,    0x1.1fd834abca2e6p-56 }, 1 }, // tanf(0.40909090638160706) == 0.43355080589241020045
    {     0x1.ba2e8c0000000p-2, {     0x1.d7e21be7b824ep-2,    0x1.280c597324109p-58 }, 1 }, // tanf(0.4318181872367859) == 0.46082347490122266677
    {     0x1.d1745e0000000p-2, {     0x1.f466d760b947fp-2,    0x1.21b5240e6aa7ap-56 }, 1 }, // tanf(0.4545454680919647) == 0.48867355850081391394
    {     0x1.e8ba2e0000000p-2, {     0x1.08c7ca53ab12cp-1,   -0x1.f57d7c1223293p-58 }, 1 }, // tanf(0.47727271914482117) == 0.51714927932110787298
    {     0x1.0000000000000p-1, {     0x1.17b4f5bf3474ap-1,    0x1.0c5e59201e209p-55 }, 1 }, // tanf(0.5) == 0.54630248984379051326
    {     0x1.0083120000000p-1, {     0x1.185f3da576451p-1,   -0x1.886f12969f560p-55 }, 1 }, // tanf(0.5009999871253967) == 0.54760162968444532536
    {     0x1.1968ba0000000p-1, {     0x1.39a5b26fbb399p-1,    0x1.f18e65d72003dp-61 }, 1 }, // tanf(0.5496271252632141) == 0.61259229291828198955
    {     0x1.324e600000000p-1, {     0x1.5cf7a7b8a8dafp-1,    0x1.1199c7195a664p-56 }, 1 }, // tanf(0.5982542037963867) == 0.68157695893426319218
    {     0x1.4b34080000000p-1, {     0x1.82b608acdffb6p-1,   -0x1.42d0e173a2fe0p-55 }, 1 }, // tanf(0.6468813419342041) == 0.75529505834855711174
    {     0x1.6419ae0000000p-1, {     0x1.ab55d23619846p-1,    0x1.c603f083e9a33p-55 }, 1 }, // tanf(0.6955084204673767) == 0.8346391383208889229
    {     0x1.7cff560000000p-1, {     0x1.d7663af1e2df4p-1,    0x1.7d485a7f8f1f9p-58 }, 1 }, // tanf(0.7441355586051941) == 0.92070182993614802475
    {     0x1.95e4fc0000000p-1, {     0x1.03cc749c072a3p+0,   -0x1.7ecea077fdf39p-59 }, 1 }, // tanf(0.7927626371383667) == 1.0148384934356406957
    {     0x1.aecaa20000000p-1, {     0x1.1e66d51f99c48p+0,    0x1.f01ab7fb4bd0ep-56 }, 1 }, // tanf(0.8413897156715393) == 1.118756599631312936
    {     0x1.c7b04a0000000p-1, {     0x1.3c117f90d326cp+0,    0x1.03229ff72007ap-54 }, 1 }, // tanf(0.8900168538093567) == 1.2346420029236027667
    {     0x1.e095f00000000p-1, {     0x1.5d87230facb1cp+0,    0x1.f9a30159a1917p-54 }, 1 }, // tanf(0.9386439323425293) == 1.3653432763355289867
    {     0x1.f97b980000000p-1, {     0x1.83c017f3edf25p+0,   -0x1.b4078f9456656p-56 }, 1 }, // tanf(0.9872710704803467) == 1.5146498652010873295
    {     0x1.0930a00000000p+0, {     0x1.b00e5d01af774p+0,    0x1.e3c0a7bf575a4p-54 }, 1 }, // tanf(1.035898208618164) == 1.6877191666712550938
    {     0x1.15a3720000000p+0, {     0x1.e44a7c100e5ccp+0,   -0x1.b003b2f2f9540p-54 }, 1 }, // tanf(1.084525227546692) == 1.8917615451049297932
    {     0x1.2216460000000p+0, {     0x1.118f3c6a27a66p+1,    0x1.85e360e8ec4edp-58 }, 1 }, // tanf(1.1331523656845093) == 2.137183715661467259
    {     0x1.2e891a0000000p+0, {     0x1.38444381baf3ep+1,    0x1.991d471820d23p-53 }, 1 }, // tanf(1.1817795038223267) == 2.4395832427452710076
    {     0x1.3afbee0000000p+0, {     0x1.69672267c0dd2p+1,   -0x1.d60d287c1a51cp-54 }, 1 }, // tanf(1.230406641960144) == 2.8234599119766493704
    {     0x1.476ec00000000p+0, {     0x1.aa316732a0df3p+1,    0x1.93f5fcaa8fa55p-53 }, 1 }, // tanf(1.2790336608886719) == 3.3296326634606374182
    {     0x1.53e1940000000p+0, {     0x1.02052da5ad457p+2,   -0x1.f253167ebcf1fp-52 }, 1 }, // tanf(1.3276607990264893) == 4.0315660589158910495
    {     0x1.6054680000000p+0, {     0x1.44dfe8084e71bp+2,    0x1.85713a302a63dp-52 }, 1 }, // tanf(1.3762879371643066) == 5.0761661606900604407
    {     0x1.6cc73a0000000p+0, {     0x1.b398981d0788bp+2,    0x1.478f0a8738060p-53 }, 1 }, // tanf(1.4249149560928345) == 6.8061886104097865413
    {     0x1.793a0e0000000p+0, {     0x1.47ff19f0ecd5fp+3,    0x1.fdc0680466212p-51 }, 1 }, // tanf(1.4735420942306519) == 10.249890299374498244
    {     0x1.85ace20000000p+0, {     0x1.48c679186cc0bp+4,   -0x1.a6980aa4df89ep-50 }, 1 }, // tanf(1.5221692323684692) == 20.548455329331810714
    {     0x1.921fb60000000p+0, {   -0x1.5d14946dc9897p+24,   -0x1.759086954a140p-30 }, 1 }, // tanf(1.5707963705062866) == -22877332.428856459874
    {     0x1.07e42a0000000p+5, {    0x1.8d4b1201a3a99p+11,   -0x1.307422c8c1912p-45 }, 1 }, // tanf(32.98640823364258) == 3178.3459480473070133
    {     0x1.0e2cfc0000000p+5, {    -0x1.001473484f3b0p+0,   -0x1.a4e3909875188p-55 }, 1 }, // tanf(33.77196502685547) == -1.0003120471512652502
    {     0x1.1475cc0000000p+5, {   -0x1.3ddbe01611c08p-20,    0x1.a01e80a914577p-74 }, 1 }, // tanf(34.557518005371094) == -1.1841166318736425066e-6
    {     0x1.1abe9e0000000p+5, {     0x1.0014a3d53c87ap+0,   -0x1.4c3b82fae134ap-54 }, 1 }, // tanf(35.343074798583984) == 1.0003149409863269338
    {     0x1.21076e0000000p+5, {   -0x1.904e6ea427870p+11,    0x1.4e728f4be16dcp-44 }, 1 }, // tanf(36.12862777709961) == -3202.4510060092942861
};

#endif // defined(HAS_TANF) || defined(HAS_LIBM_SSE2)

#if defined(HAS_TANF)

void Test_tanf_approx(void)
{
    for (int i = 0; i < _countof(s_tanf_approx_tests); i++)
    {
        float x = s_tanf_approx_tests[i].x;
        float expected = s_tanf_approx_tests[i].expected.rounded;
        float z = tanf(x);
        int64_t error = abs(ulp_error_flt(expected, z));
        ok(error <= s_tan_approx_tests[i].max_error,
            "tan(%.6e) = %.7e, expected %.7e, error %I64d ULPs, max %u ULPs\n",
            x, z, expected, error, s_tan_approx_tests[i].max_error);
    }
}

#endif // defined(HAS_TANF)

#if defined(HAS_LIBM_SSE2)

__ATTRIBUTE_SSE2__ __m128d __libm_sse2_tan(__m128d Xmm0);

__ATTRIBUTE_SSE2__
void Test_libm_sse2_tan(void)
{
    int i;
    for (i = 0; i < _countof(s_tan_approx_tests); i++)
    {
        double x = s_tan_approx_tests[i].x;
        double expected = s_tan_approx_tests[i].expected.rounded;
        __m128d xmm0 = _mm_set_sd(x);
        __m128d xmm1 = __libm_sse2_tan(xmm0);
        double z = _mm_cvtsd_f64(xmm1);
        int64_t error = ulp_error_precise(&s_tan_approx_tests[i].expected, z);
        ok(error <= s_tan_approx_tests[i].max_error,
            "__libm_sse2_tan(%.17e) = %.17e, expected %.17e, error %I64d ULPs, max %u ULPs\n",
            x, z, expected, error, s_tan_approx_tests[i].max_error);
    }
}

__ATTRIBUTE_SSE2__ __m128 __libm_sse2_tanf(__m128 Xmm0);

__ATTRIBUTE_SSE2__
void Test_libm_sse2_tanf(void)
{
    int i;
    for (i = 0; i < _countof(s_tanf_approx_tests); i++)
    {
        float x = s_tanf_approx_tests[i].x;
        float expected = s_tanf_approx_tests[i].expected.rounded;
        __m128 xmm0 = _mm_set_ps1(x);
        __m128 xmm1 = __libm_sse2_tanf(xmm0);
        float z = _mm_cvtss_f32(xmm1);
        int64_t error = ulp_error_flt(expected, z);
        ok(error <= s_tanf_approx_tests[i].max_error,
            "__libm_sse2_tanf(%.6e) = %.7e, expected %.7e, error %I64d ULPs, max %u ULPs\n",
            x, z, expected, error, s_tanf_approx_tests[i].max_error);
    }
}

#endif // defined(HAS_LIBM_SSE2)

START_TEST(tan)
{
    Test_tan_exact();
    Test_tan_approx();
#if defined(HAS_TANF)
    Test_tanf_exact();
    Test_tanf_approx();
#endif
#if defined(HAS_LIBM_SSE2)
    Test_libm_sse2_tan();
    Test_libm_sse2_tanf();
#endif
}
